#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <string>
#include "TFile.h"
#include "TTree.h"
#include "TH1F.h"
#include "TH2F.h"

#include "CommandLineInterface.hh"
#include "BuiltEvent.hh"

using namespace std;

ClassImp(BuiltEvent);
ClassImp(AdcData);
ClassImp(DgfData);

int main(int argc, char* argv[]){
  char* InputFile = NULL;
  char* OutputFile = NULL;
  char* ZeroFile = NULL;
  bool verbose = false;
  CommandLineInterface* interface = new CommandLineInterface();

  interface->Add("-i", "inputfile", &InputFile);
  interface->Add("-o", "outputfile", &OutputFile);
  interface->Add("-zf", "zerosfile", &ZeroFile);
  interface->Add("-v", "verbose", &verbose);

  interface->CheckFlags(argc, argv);

  if(InputFile == NULL || OutputFile == NULL ){
    cerr<<"You have to provide both the input file and the output file!"<<endl;
    exit(1);
  }
  if(ZeroFile == NULL){
    cerr<<"You have to provide the file with the zeros!"<<endl;
    exit(1);
  }

  cout<<"input file: "<<InputFile<< endl;
  cout<<"zero file: "<<ZeroFile<< endl;

  int adcmod, adcchan;
  double value;

  int i,j,k,l,m;
  float stripoffset[4][32]={0};
  float stripfwhm[4][32]={0};
  float rearoffset[4][2]={0};
  float threshrear[4][2]={0};

  ifstream zerofile(ZeroFile);
  char Name[20];
  zerofile.ignore(1000, '\n');

  for(j=0;j<4;j++){
    for(k=0;k<32;k++){
      zerofile >> value >> stripoffset[j][k] >> stripfwhm[j][k] >> value >> Name ;
      zerofile.ignore(1000, '\n');
      //cout << Name << "\t" << stripoffset[j][k] << "\t" << stripfwhm[j][k] << endl;
    }
  }
  zerofile.ignore(1000, '\n');
  for(j=0;j<4;j++){
    for(k=0;k<2;k++){
      zerofile >> value >> rearoffset[j][k] >> threshrear[j][k] >> Name;
      zerofile.ignore(1000, '\n');
      //cout << Name << "\t" << rearoffset[j][k] << "\t" << rearfwhm[j][k] << endl;
    }
  }
  zerofile.close();


  TFile* infile = new TFile(InputFile);

  if(infile->IsZombie()){
    return 2;
  }

  TTree* tr = (TTree*) infile->Get("tr");

  if(tr == NULL){
    cout << "could not find tree tr in file " << infile->GetName() << endl;
    return 3;
  }

  BuiltEvent* event = new BuiltEvent;

  tr->SetBranchAddress("Event",&event);

  TFile* outfile = new TFile(OutputFile,"recreate");

  if(outfile->IsZombie()){
    return 4;
  }
  TH1F *Forward_strips[4][16];
  TH1F *Backward_strips[4][16];
  TH2F *Forward_strips_2d[4];
  TH2F *Backward_strips_2d[4];
  TH2F *frear_pos_top[16];
  TH2F *frear_pos_left[16];
  TH2F *frear_pos_bottom[16];
  TH2F *frear_pos_right[16];
  TH2F *brear_pos_top[16];
  TH2F *brear_pos_left[16];
  TH2F *brear_pos_bottom[16];
  TH2F *brear_pos_right[16];
  float strip[8][16]={-1};
  float rear[8]={-1};
  float stripthresh[8][16]={-1};
  float rearthresh[8]={-1};
  int forward = -1; // 0 forward, 1 backward
  for(j=0;j<4;j++){
    for(k=0;k<16;k++){
      Forward_strips[j][k] = new TH1F(Form("Forward_strips_%d_%d",j,k),Form("Forward_strips_%d_%d",j,k),4000,0,5);
      Backward_strips[j][k] = new TH1F(Form("Backward_strips_%d_%d",j,k),Form("Backward_strips_%d_%d",j,k),4000,0,5);
    }
    Forward_strips_2d[j] = new TH2F(Form("Forward_strips_2d_%d",j),Form("Forward_strips_2d_%d",j),16,0,16,4000,0,5);
    Backward_strips_2d[j] = new TH2F(Form("Backward_strips_2d_%d",j),Form("Backward_strips_2d_%d",j),16,0,16,4000,0,5);
  }
  for(j=0;j<16;j++){
    frear_pos_top[j] = new TH2F(Form("frear_pos_top_%d",j),Form("frear_pos_top_%d",j),1000,0,5,1000,0,4000);
    frear_pos_left[j] = new TH2F(Form("frear_pos_left_%d",j),Form("frear_pos_left_%d",j),1000,0,5,1000,0,4000);
    frear_pos_bottom[j] = new TH2F(Form("frear_pos_bottom_%d",j),Form("frear_pos_bottom_%d",j),1000,0,5,1000,0,4000);
    frear_pos_right[j] = new TH2F(Form("frear_pos_right_%d",j),Form("frear_pos_right_%d",j),1000,0,5,1000,0,4000);
    brear_pos_top[j] = new TH2F(Form("brear_pos_top_%d",j),Form("brear_pos_top_%d",j),1000,0,5,1000,0,4000);
    brear_pos_left[j] = new TH2F(Form("brear_pos_left_%d",j),Form("brear_pos_left_%d",j),1000,0,5,1000,0,4000);
    brear_pos_bottom[j] = new TH2F(Form("brear_pos_bottom_%d",j),Form("brear_pos_bottom_%d",j),1000,0,5,1000,0,4000);
    brear_pos_right[j] = new TH2F(Form("brear_pos_right_%d",j),Form("brear_pos_right_%d",j),1000,0,5,1000,0,4000);
  }
  Double_t nentries = tr->GetEntries();
  Int_t nbytes = 0;
  Int_t status;
  vector<int> DgfModule;
  for(i=0; i<nentries;i++){
    //cout << "@@@@@@@@@@@@@@@@@@@ next event @@@@@@@@@@@@@@@@@" << endl;
    status = tr->GetEvent(i);
    if(status == -1){
      cerr<<"Error occured, couldn't read entry "<<i<<" from tree "<<tr->GetName()<<" in file "<<infile->GetName()<<endl;
      return 5;
    }
    else if(status == 0){
      cerr<<"Error occured, entry "<<i<<" in tree "<<tr->GetName()<<" in file "<<infile->GetName()<<" doesn't exist"<<endl;
      return 6;
    }
    nbytes += status;
   
    for(l=0; l<event->NumberOfAdcs(); l++){
      for(j=0;j<8;j++){
	for(k=0;k<16;k++)
	  strip[j][k]=0.;
      }
      //cout << "-------------------next l-----------------" << endl;
      for(m=0; m<event->Adc(l)->SubEvent()->Size(); m++){
	adcmod = event->Adc(l)->ModuleNumber();
	adcchan = event->Adc(l)->SubEvent()->AdcChannel(m);
	if(adcmod == 2){ //top left rear forward 0,4 backward 2,6
	  forward = -1;
	  switch(adcchan){
	  case 0: //FT
	    forward = 0;
	    rear[0] = event->Adc(l)->SubEvent()->AdcValue(m) - rearoffset[0][forward];
	    rearthresh[0] = threshrear[0][forward];
	    break;
	  case 2: //BT
	    forward = 1;
	    rear[4] = event->Adc(l)->SubEvent()->AdcValue(m) - rearoffset[0][forward];
	    rearthresh[4] = threshrear[0][forward];
	    break;
	  case 4: //FL
	    forward = 0;
	    rear[1] = event->Adc(l)->SubEvent()->AdcValue(m) - rearoffset[1][forward];
	    rearthresh[1] = threshrear[1][forward];
	    break;
	  case 6: //BL
	    forward = 1;
	    rear[5] = event->Adc(l)->SubEvent()->AdcValue(m) - rearoffset[1][forward];
	    rearthresh[5] = threshrear[1][forward];
	    if(verbose)
	      //cout << "rear adc " << adcmod << " chan " << adcchan << " value " << event->Adc(l)->SubEvent()->AdcValue(m) << " offset " << rearoffset[1][forward] << " fwhm " << rearfwhm[1][forward] << " result " << rear[5] << endl;
	    break;
	  default:
	    break;    
	  }
	}
	else if(adcmod == 5){ //bottom right rear forward 0,4 backward 2,6
	  forward = -1;
	  switch(adcchan){
	  case 0: //FB
	    forward = 0;
	    rear[2] = event->Adc(l)->SubEvent()->AdcValue(m) - rearoffset[2][forward];
	    rearthresh[2] = threshrear[2][forward];
	    break;
	  case 2: //BB
	    forward = 1;
	    rear[6] = event->Adc(l)->SubEvent()->AdcValue(m) - rearoffset[2][forward];
	    rearthresh[6] = threshrear[2][forward];
	    break;
	  case 4: //FR
	    forward = 0;
	    rear[3] = event->Adc(l)->SubEvent()->AdcValue(m) - rearoffset[3][forward];
	    rearthresh[3] = threshrear[3][forward];
	    break;
	  case 6: //BR
	    forward = 1;
	    rear[7] = event->Adc(l)->SubEvent()->AdcValue(m) - rearoffset[3][forward];
	    rearthresh[7] = threshrear[3][forward];
	    break;
	  default:
	    break;    
	  }
	}
	else if(adcmod<5){
	  forward = -1;
	  if(adcmod>2)
	    adcmod-=1;
	  if(adcchan<16)
	    forward = 0;
	  if(adcchan>15){
	    adcchan-=16;
	    forward = 1;
	  }
	  if(forward>-1){
   	    if(rear[adcmod+4*forward]>rearthresh[adcmod+4*forward]){
	      //cout << "rear[adcmod+4*forward] = rear["<<adcmod+4*forward<<"] " << rear[adcmod+4*forward] << endl;
	      if( (event->Adc(l)->SubEvent()->AdcValue(m) - stripoffset[adcmod][adcchan+16*forward])> strip[adcmod+4*forward][adcchan] )
		strip[adcmod+4*forward][adcchan]=event->Adc(l)->SubEvent()->AdcValue(m) - stripoffset[adcmod][adcchan+16*forward];
	      else
		continue;
	      
	      
	      stripthresh[adcmod+4*forward][adcchan] = stripfwhm[adcmod][adcchan+16*forward];
	      if(verbose){
		cout << "strip adc " << event->Adc(l)->ModuleNumber() << " chan " << event->Adc(l)->SubEvent()->AdcChannel(m) << " adcmod " << adcmod << " adcchan " << adcchan << endl;
		cout << " value " << event->Adc(l)->SubEvent()->AdcValue(m) << " offset " << stripoffset[adcmod][adcchan+16*forward] << " fwhm " << stripfwhm[adcmod][adcchan+16*forward] << " result " << strip[adcmod+4*forward][adcchan] << endl;
		cout << "strip["<<adcmod+4*forward<<"]["<<adcchan<<"] " << strip[adcmod+4*forward][adcchan] << endl;
	      }
	    }
	  }
	}
	else
	  continue;
	
      }

      for(j=0;j<8;j++){
	if(rear[j]>rearthresh[j]){ // energy in that rear
	  
	  for(k=0;k<16;k++){
	    if(strip[j][k]>stripthresh[j][k]){ // energy in that strip
	      if(j<4){  // forward
		if(verbose)
		  cout << "forward strip " << strip[j][k] << " rear " << rear[j] << " ratio " << strip[j][k]/rear[j] << endl;
		Forward_strips[j][k]->Fill(strip[j][k]/rear[j]);
		Forward_strips_2d[j]->Fill(k,strip[j][k]/rear[j]);
		if(j==0)
		  frear_pos_top[k]->Fill(strip[j][k]/rear[j], rear[j]);
		if(j==1)
		  frear_pos_left[k]->Fill(strip[j][k]/rear[j], rear[j]);
		if(j==2)
		  frear_pos_bottom[k]->Fill(strip[j][k]/rear[j], rear[j]);
		if(j==3)
		  frear_pos_right[k]->Fill(strip[j][k]/rear[j], rear[j]);
	      }
	      else{ //backward
		if(verbose)
		  cout << "backward strip["<<j<<"]["<<k<<"] " << strip[j][k] << " rear " << rear[j] << " ratio " << strip[j][k]/rear[j] << endl;
		Backward_strips[j-4][k]->Fill(strip[j][k]/rear[j]);	  
		Backward_strips_2d[j-4]->Fill(k,strip[j][k]/rear[j]);
		if(j==4)
		  brear_pos_top[k]->Fill(strip[j][k]/rear[j], rear[j]);
		if(j==5)
		  brear_pos_left[k]->Fill(strip[j][k]/rear[j], rear[j]);
		if(j==6)
		  brear_pos_bottom[k]->Fill(strip[j][k]/rear[j], rear[j]);
		if(j==7)
		  brear_pos_right[k]->Fill(strip[j][k]/rear[j], rear[j]);
	      }
	    } // energy in that strip
	  }
	} // energy in that rear
      }
      
    }


    if(i%1000 == 0){
      cout<<setw(5)<<setiosflags(ios::fixed)<<setprecision(1)<<(100.*i)/nentries<<" % done\r"<<flush;
    }
    
  }
  for(j=0;j<4;j++){
    for(k=0;k<16;k++){
      Forward_strips[j][k]->Write("",TObject::kOverwrite);
    }
  }
  for(j=0;j<4;j++){
    for(k=0;k<16;k++){
      Backward_strips[j][k]->Write("",TObject::kOverwrite);
    }
  }
  for(j=0;j<4;j++){
    Forward_strips_2d[j]->Write("",TObject::kOverwrite);
    Backward_strips_2d[j]->Write("",TObject::kOverwrite);
  }
  for(j=0;j<16;j++){
    frear_pos_top[j]->Write("",TObject::kOverwrite);
    brear_pos_top[j]->Write("",TObject::kOverwrite);
  }
  for(j=0;j<16;j++){
    frear_pos_left[j]->Write("",TObject::kOverwrite);
    brear_pos_left[j]->Write("",TObject::kOverwrite);
  }
  for(j=0;j<16;j++){
    frear_pos_bottom[j]->Write("",TObject::kOverwrite);
    brear_pos_bottom[j]->Write("",TObject::kOverwrite);
  }
  for(j=0;j<16;j++){
    frear_pos_right[j]->Write("",TObject::kOverwrite);
    brear_pos_right[j]->Write("",TObject::kOverwrite);
  }
  infile->Close();
  outfile->Close();
  return 0;
}
